-
Notifications
You must be signed in to change notification settings - Fork 15.2k
Revert "[Clang] Normalize constraints before checking for satisfaction" #161669
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Revert "[Clang] Normalize constraints before checking for satisfaction" #161669
Conversation
@llvm/pr-subscribers-clang @llvm/pr-subscribers-libcxx Author: Corentin Jabot (cor3ntin) ChangesReverts llvm/llvm-project#141776 CI failures https://lab.llvm.org/buildbot/#/builders/202/builds/3591 Patch is 266.00 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/161669.diff 50 Files Affected:
diff --git a/clang/docs/InternalsManual.rst b/clang/docs/InternalsManual.rst
index c677ddfa5ecc1..bd742273f4ed5 100644
--- a/clang/docs/InternalsManual.rst
+++ b/clang/docs/InternalsManual.rst
@@ -2859,67 +2859,6 @@ This library is called by the :ref:`Parser library <Parser>` during parsing to
do semantic analysis of the input. For valid programs, Sema builds an AST for
parsed constructs.
-
-Concept Satisfaction Checking and Subsumption
----------------------------------------------
-
-As per the C++ standard, constraints are `normalized <https://eel.is/c++draft/temp.constr.normal>`_
-and the normal form is used both for subsumption, and constraint checking.
-Both depend on a parameter mapping that substitutes lazily. In particular,
-we should not substitute in unused arguments.
-
-Clang follows the order of operations prescribed by the standard.
-
-Normalization happens prior to satisfaction and subsumption
-and is handled by ``NormalizedConstraint``.
-
-Clang preserves in the normalized form intermediate concept-ids
-(``ConceptIdConstraint``) This is used for diagnostics only and no substitution
-happens in a ConceptIdConstraint if its expression is satisfied.
-
-The normal form of the associated constraints of a declaration is cached in
-Sema::NormalizationCache such that it is only computed once.
-
-A ``NormalizedConstraint`` is a recursive data structure, where each node
-contains a parameter mapping, represented by the indexes of all parameter
-being used.
-
-Checking satisfaction is done by ``ConstraintSatisfactionChecker``, recursively
-walking ``NormalizedConstraint``. At each level, we substitute the outermost
-level of the template arguments referenced in the parameter mapping of a
-normalized expression (``MultiLevelTemplateArgumentList``).
-
-For the following example,
-
-.. code-block:: c++
-
- template <typename T>
- concept A = __is_same(T, int);
-
- template <typename U>
- concept B = A<U> && __is_same(U, int);
-
-The normal form of B is
-
-.. code-block:: c++
-
- __is_same(T, int) /*T->U, innermost level*/
- && __is_same(U, int) {U->U} /*T->U, outermost level*/
-
-After substitution in the mapping, we substitute in the constraint expression
-using that copy of the ``MultiLevelTemplateArgumentList``, and then evaluate it.
-
-Because this is expensive, it is cached in
-``UnsubstitutedConstraintSatisfactionCache``.
-
-Any error during satisfaction is recorded in ``ConstraintSatisfaction``.
-for nested requirements, ``ConstraintSatisfaction`` is stored (including
-diagnostics) in the AST, which is something we might want to improve.
-
-When an atomic constraint is not satified, we try to substitute into any
-enclosing concept-id using the same mechanism described above, for
-diagnostics purpose, and inject that in the ``ConstraintSatisfaction``.
-
.. _CodeGen:
The CodeGen Library
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index a1e3a0c51d8e1..c6ee1e282a008 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -160,10 +160,6 @@ C++23 Feature Support
C++20 Feature Support
^^^^^^^^^^^^^^^^^^^^^
-- Clang now normalizes constraints before checking whether they are satisfied, as mandated by the standard.
- As a result, Clang no longer incorrectly diagnoses substitution failures in template arguments only
- used in concept-ids, and produces better diagnostics for satisfaction failure. (#GH61811) (#GH135190)
-
C++17 Feature Support
^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/include/clang/AST/ASTConcept.h b/clang/include/clang/AST/ASTConcept.h
index f362f24ebc72a..72da0059744f2 100644
--- a/clang/include/clang/AST/ASTConcept.h
+++ b/clang/include/clang/AST/ASTConcept.h
@@ -28,20 +28,10 @@ namespace clang {
class ConceptDecl;
class TemplateDecl;
-class ConceptReference;
class Expr;
class NamedDecl;
struct PrintingPolicy;
-/// Unsatisfied constraint expressions if the template arguments could be
-/// substituted into them, or a diagnostic if substitution resulted in
-/// an invalid expression.
-///
-using ConstraintSubstitutionDiagnostic = std::pair<SourceLocation, StringRef>;
-using UnsatisfiedConstraintRecord =
- llvm::PointerUnion<const Expr *, const ConceptReference *,
- const ConstraintSubstitutionDiagnostic *>;
-
/// The result of a constraint satisfaction check, containing the necessary
/// information to diagnose an unsatisfied constraint.
class ConstraintSatisfaction : public llvm::FoldingSetNode {
@@ -58,13 +48,16 @@ class ConstraintSatisfaction : public llvm::FoldingSetNode {
ArrayRef<TemplateArgument> TemplateArgs)
: ConstraintOwner(ConstraintOwner), TemplateArgs(TemplateArgs) {}
+ using SubstitutionDiagnostic = std::pair<SourceLocation, StringRef>;
+ using Detail = llvm::PointerUnion<Expr *, SubstitutionDiagnostic *>;
+
bool IsSatisfied = false;
bool ContainsErrors = false;
/// \brief The substituted constraint expr, if the template arguments could be
/// substituted into them, or a diagnostic if substitution resulted in an
/// invalid expression.
- llvm::SmallVector<UnsatisfiedConstraintRecord, 4> Details;
+ llvm::SmallVector<Detail, 4> Details;
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &C) {
Profile(ID, C, ConstraintOwner, TemplateArgs);
@@ -76,12 +69,19 @@ class ConstraintSatisfaction : public llvm::FoldingSetNode {
bool HasSubstitutionFailure() {
for (const auto &Detail : Details)
- if (Detail.dyn_cast<const ConstraintSubstitutionDiagnostic *>())
+ if (Detail.dyn_cast<SubstitutionDiagnostic *>())
return true;
return false;
}
};
+/// Pairs of unsatisfied atomic constraint expressions along with the
+/// substituted constraint expr, if the template arguments could be
+/// substituted into them, or a diagnostic if substitution resulted in
+/// an invalid expression.
+using UnsatisfiedConstraintRecord =
+ llvm::PointerUnion<Expr *, std::pair<SourceLocation, StringRef> *>;
+
/// \brief The result of a constraint satisfaction check, containing the
/// necessary information to diagnose an unsatisfied constraint.
///
@@ -101,10 +101,6 @@ struct ASTConstraintSatisfaction final :
return getTrailingObjects() + NumRecords;
}
- ArrayRef<UnsatisfiedConstraintRecord> records() const {
- return {begin(), end()};
- }
-
ASTConstraintSatisfaction(const ASTContext &C,
const ConstraintSatisfaction &Satisfaction);
ASTConstraintSatisfaction(const ASTContext &C,
@@ -286,11 +282,6 @@ class TypeConstraint {
}
};
-/// Insertion operator for diagnostics. This allows sending ConceptReferences's
-/// into a diagnostic with <<.
-const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
- const ConceptReference *C);
-
} // clang
#endif // LLVM_CLANG_AST_ASTCONCEPT_H
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index 78220d4d8ff5b..12351e98e5a2b 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -3877,6 +3877,7 @@ typename clang::LazyGenerationalUpdatePtr<Owner, T, Update>::ValueType
return new (Ctx) LazyData(Source, Value);
return Value;
}
+
template <> struct llvm::DenseMapInfo<llvm::FoldingSetNodeID> {
static FoldingSetNodeID getEmptyKey() { return FoldingSetNodeID{}; }
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index bd3e042868299..f53aafdeb4f36 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -65,7 +65,6 @@
#include "clang/Sema/Redeclaration.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/SemaBase.h"
-#include "clang/Sema/SemaConcept.h"
#include "clang/Sema/TypoCorrection.h"
#include "clang/Sema/Weak.h"
#include "llvm/ADT/APInt.h"
@@ -11695,9 +11694,8 @@ class Sema final : public SemaBase {
ExprResult
CheckConceptTemplateId(const CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
const DeclarationNameInfo &ConceptNameInfo,
- NamedDecl *FoundDecl, TemplateDecl *NamedConcept,
- const TemplateArgumentListInfo *TemplateArgs,
- bool DoCheckConstraintSatisfaction = true);
+ NamedDecl *FoundDecl, ConceptDecl *NamedConcept,
+ const TemplateArgumentListInfo *TemplateArgs);
void diagnoseMissingTemplateArguments(TemplateName Name, SourceLocation Loc);
void diagnoseMissingTemplateArguments(const CXXScopeSpec &SS,
@@ -12027,13 +12025,6 @@ class Sema final : public SemaBase {
bool UpdateArgsWithConversions = true,
bool *ConstraintsNotSatisfied = nullptr);
- bool CheckTemplateArgumentList(
- TemplateDecl *Template, TemplateParameterList *Params,
- SourceLocation TemplateLoc, TemplateArgumentListInfo &TemplateArgs,
- const DefaultArguments &DefaultArgs, bool PartialTemplateArgs,
- CheckTemplateArgumentInfo &CTAI, bool UpdateArgsWithConversions = true,
- bool *ConstraintsNotSatisfied = nullptr);
-
bool CheckTemplateTypeArgument(
TemplateTypeParmDecl *Param, TemplateArgumentLoc &Arg,
SmallVectorImpl<TemplateArgument> &SugaredConverted,
@@ -12792,18 +12783,6 @@ class Sema final : public SemaBase {
void MarkUsedTemplateParameters(const Expr *E, bool OnlyDeduced,
unsigned Depth, llvm::SmallBitVector &Used);
- /// Mark which template parameters are named in a given expression.
- ///
- /// Unlike MarkUsedTemplateParameters, this excludes parameter that
- /// are used but not directly named by an expression - i.e. it excludes
- /// any template parameter that denotes the type of a referenced NTTP.
- ///
- /// \param Used a bit vector whose elements will be set to \c true
- /// to indicate when the corresponding template parameter will be
- /// deduced.
- void MarkUsedTemplateParametersForSubsumptionParameterMapping(
- const Expr *E, unsigned Depth, llvm::SmallBitVector &Used);
-
/// Mark which template parameters can be deduced from a given
/// template argument list.
///
@@ -12820,9 +12799,6 @@ class Sema final : public SemaBase {
void MarkUsedTemplateParameters(ArrayRef<TemplateArgument> TemplateArgs,
unsigned Depth, llvm::SmallBitVector &Used);
- void MarkUsedTemplateParameters(ArrayRef<TemplateArgumentLoc> TemplateArgs,
- unsigned Depth, llvm::SmallBitVector &Used);
-
void
MarkDeducedTemplateParameters(const FunctionTemplateDecl *FunctionTemplate,
llvm::SmallBitVector &Deduced) {
@@ -13120,9 +13096,6 @@ class Sema final : public SemaBase {
/// Whether we're substituting into constraints.
bool InConstraintSubstitution;
- /// Whether we're substituting into the parameter mapping of a constraint.
- bool InParameterMappingSubstitution;
-
/// The point of instantiation or synthesis within the source code.
SourceLocation PointOfInstantiation;
@@ -13386,11 +13359,6 @@ class Sema final : public SemaBase {
const MultiLevelTemplateArgumentList &TemplateArgs,
TemplateArgumentListInfo &Outputs);
- bool SubstTemplateArgumentsInParameterMapping(
- ArrayRef<TemplateArgumentLoc> Args, SourceLocation BaseLoc,
- const MultiLevelTemplateArgumentList &TemplateArgs,
- TemplateArgumentListInfo &Out, bool BuildPackExpansionTypes);
-
/// Retrieve the template argument list(s) that should be used to
/// instantiate the definition of the given declaration.
///
@@ -13852,12 +13820,6 @@ class Sema final : public SemaBase {
CodeSynthesisContexts.back().InConstraintSubstitution;
}
- bool inParameterMappingSubstitution() const {
- return !CodeSynthesisContexts.empty() &&
- CodeSynthesisContexts.back().InParameterMappingSubstitution &&
- !inConstraintSubstitution();
- }
-
using EntityPrinter = llvm::function_ref<void(llvm::raw_ostream &)>;
/// \brief create a Requirement::SubstitutionDiagnostic with only a
@@ -14742,10 +14704,6 @@ class Sema final : public SemaBase {
SatisfactionStack.swap(NewSS);
}
- using ConstrainedDeclOrNestedRequirement =
- llvm::PointerUnion<const NamedDecl *,
- const concepts::NestedRequirement *>;
-
/// Check whether the given expression is a valid constraint expression.
/// A diagnostic is emitted if it is not, false is returned, and
/// PossibleNonPrimary will be set to true if the failure might be due to a
@@ -14770,12 +14728,44 @@ class Sema final : public SemaBase {
/// \returns true if an error occurred and satisfaction could not be checked,
/// false otherwise.
bool CheckConstraintSatisfaction(
- ConstrainedDeclOrNestedRequirement Entity,
+ const NamedDecl *Template,
ArrayRef<AssociatedConstraint> AssociatedConstraints,
const MultiLevelTemplateArgumentList &TemplateArgLists,
- SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction,
- const ConceptReference *TopLevelConceptId = nullptr,
- Expr **ConvertedExpr = nullptr);
+ SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction) {
+ llvm::SmallVector<Expr *, 4> Converted;
+ return CheckConstraintSatisfaction(Template, AssociatedConstraints,
+ Converted, TemplateArgLists,
+ TemplateIDRange, Satisfaction);
+ }
+
+ /// \brief Check whether the given list of constraint expressions are
+ /// satisfied (as if in a 'conjunction') given template arguments.
+ /// Additionally, takes an empty list of Expressions which is populated with
+ /// the instantiated versions of the ConstraintExprs.
+ /// \param Template the template-like entity that triggered the constraints
+ /// check (either a concept or a constrained entity).
+ /// \param ConstraintExprs a list of constraint expressions, treated as if
+ /// they were 'AND'ed together.
+ /// \param ConvertedConstraints a out parameter that will get populated with
+ /// the instantiated version of the ConstraintExprs if we successfully checked
+ /// satisfaction.
+ /// \param TemplateArgList the multi-level list of template arguments to
+ /// substitute into the constraint expression. This should be relative to the
+ /// top-level (hence multi-level), since we need to instantiate fully at the
+ /// time of checking.
+ /// \param TemplateIDRange The source range of the template id that
+ /// caused the constraints check.
+ /// \param Satisfaction if true is returned, will contain details of the
+ /// satisfaction, with enough information to diagnose an unsatisfied
+ /// expression.
+ /// \returns true if an error occurred and satisfaction could not be checked,
+ /// false otherwise.
+ bool CheckConstraintSatisfaction(
+ const NamedDecl *Template,
+ ArrayRef<AssociatedConstraint> AssociatedConstraints,
+ llvm::SmallVectorImpl<Expr *> &ConvertedConstraints,
+ const MultiLevelTemplateArgumentList &TemplateArgList,
+ SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction);
/// \brief Check whether the given non-dependent constraint expression is
/// satisfied. Returns false and updates Satisfaction with the satisfaction
@@ -14841,17 +14831,16 @@ class Sema final : public SemaBase {
/// \param First whether this is the first time an unsatisfied constraint is
/// diagnosed for this error.
void DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction &Satisfaction,
- SourceLocation Loc = {},
bool First = true);
/// \brief Emit diagnostics explaining why a constraint expression was deemed
/// unsatisfied.
void
- DiagnoseUnsatisfiedConstraint(const ConceptSpecializationExpr *ConstraintExpr,
+ DiagnoseUnsatisfiedConstraint(const ASTConstraintSatisfaction &Satisfaction,
bool First = true);
const NormalizedConstraint *getNormalizedAssociatedConstraints(
- ConstrainedDeclOrNestedRequirement Entity,
+ const NamedDecl *ConstrainedDecl,
ArrayRef<AssociatedConstraint> AssociatedConstraints);
/// \brief Check whether the given declaration's associated constraints are
@@ -14876,15 +14865,6 @@ class Sema final : public SemaBase {
const NamedDecl *D1, ArrayRef<AssociatedConstraint> AC1,
const NamedDecl *D2, ArrayRef<AssociatedConstraint> AC2);
- /// Cache the satisfaction of an atomic constraint.
- /// The key is based on the unsubstituted expression and the parameter
- /// mapping. This lets us not substituting the mapping more than once,
- /// which is (very!) expensive.
- /// FIXME: this should be private.
- llvm::DenseMap<llvm::FoldingSetNodeID,
- UnsubstitutedConstraintSatisfactionCacheResult>
- UnsubstitutedConstraintSatisfactionCache;
-
private:
/// Caches pairs of template-like decls whose associated constraints were
/// checked for subsumption and whether or not the first's constraints did in
@@ -14895,11 +14875,8 @@ class Sema final : public SemaBase {
/// constrained declarations). If an error occurred while normalizing the
/// associated constraints of the template or concept, nullptr will be cached
/// here.
- llvm::DenseMap<ConstrainedDeclOrNestedRequirement, NormalizedConstraint *>
- NormalizationCache;
+ llvm::DenseMap<const NamedDecl *, NormalizedConstraint *> NormalizationCache;
- /// Cache whether the associated constraint of a declaration
- /// is satisfied.
llvm::ContextualFoldingSet<ConstraintSatisfaction, const ASTContext &>
SatisfactionCache;
diff --git a/clang/include/clang/Sema/SemaConcept.h b/clang/include/clang/Sema/SemaConcept.h
index 51ca1e16331f5..648a9c51ae6c1 100644
--- a/clang/include/clang/Sema/SemaConcept.h
+++ b/clang/include/clang/Sema/SemaConcept.h
@@ -16,406 +16,130 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
-#include "clang/AST/ExprConcepts.h"
#include "clang/Basic/SourceLocation.h"
-#include "clang/Sema/Ownership.h"
#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/STLFunctionalExtras.h"
-#include "llvm/ADT/SmallBitVector.h"
#include "llvm/ADT/SmallVector.h"
#include <optional>
#include <utility>
namespace clang {
class Sema;
-class MultiLevelTemplateArgumentList;
-/// \brief A normalized constraint, as defined in C++ [temp.constr.normal], is
-/// either an atomic constraint, a conjunction of normalized constraints or a
-/// disjunction of normalized constraints.
-struct NormalizedConstraint {
-
- enum class ConstraintKind : unsigned char {
- Atomic = 0,
- ConceptId,
- FoldExpanded,
- Compound,
- };
-
- enum CompoundConstraintKind : unsigned char {
- CCK_Conjunction,
- CCK_Disjunction
- };
- enum class FoldOperatorKind : unsigned char { And, Or };
-
- using OccurenceList = llvm::SmallBitVector;
-
-protected:
- using ExprOrConcept =
- llvm::PointerUnion<const Expr *, const ConceptReference *>;
-
- struct AtomicConstraintBits {
- // Kind is the first member of all union members,
- // as we rely on their initial common sequence.
- LLVM_PREFERRED_TYPE(ConstraintKind)
- unsigned Kind : 5;
- unsigned Placeholder : 1;
- unsigned PackSubstitutionIndex : 26;
- // Indexes, IndexesForSubsumption, and Args are part of the common initial
- // sequences of constraints that do have a mapping.
-
- // Indexes of the parameters used in a constraint expression.
- OccurenceList Indexes;
- // Indexes of the parameters named directly in a constraint expression.
- // FIXME: we should try to reduce the size of this struct?
- OccurenceList IndexesForSubsumption;
-
- TemplateArgumentLoc *Args;
- TemplateParameterList *ParamList;
- ExprOrConcept ConstraintExpr;
- const NamedDecl *ConstraintDecl;
- };
-
- struct FoldExpandedConstraintBits {
- LLVM_PREFERRED_TYPE(ConstraintKind)
- unsigned Kind : 5;
- LLVM_PREFERRED_TYPE(FoldOperatorKind)
- unsigned FoldOperator : 1;
- unsigned Placeholder : 26;
- Occu...
[truncated]
|
You can test this locally with the following command:git-clang-format --diff origin/main HEAD --extensions cpp,h -- clang/include/clang/AST/ASTConcept.h clang/include/clang/AST/ASTContext.h clang/include/clang/Sema/Sema.h clang/include/clang/Sema/SemaConcept.h clang/include/clang/Sema/Template.h clang/lib/AST/ASTConcept.cpp clang/lib/AST/ASTImporter.cpp clang/lib/Sema/SemaConcept.cpp clang/lib/Sema/SemaDeclCXX.cpp clang/lib/Sema/SemaExprCXX.cpp clang/lib/Sema/SemaOverload.cpp clang/lib/Sema/SemaTemplate.cpp clang/lib/Sema/SemaTemplateDeduction.cpp clang/lib/Sema/SemaTemplateInstantiate.cpp clang/lib/Sema/TreeTransform.h clang/lib/Serialization/ASTReaderDecl.cpp clang/lib/Serialization/ASTReaderStmt.cpp clang/lib/Serialization/ASTWriterStmt.cpp clang/test/AST/ast-dump-concepts.cpp clang/test/AST/ast-dump-ctad-alias.cpp clang/test/CXX/drs/cwg25xx.cpp clang/test/CXX/expr/expr.prim/expr.prim.id/p3.cpp clang/test/CXX/expr/expr.prim/expr.prim.req/compound-requirement.cpp clang/test/CXX/expr/expr.prim/expr.prim.req/nested-requirement.cpp clang/test/CXX/expr/expr.prim/expr.prim.req/simple-requirement.cpp clang/test/CXX/expr/expr.prim/expr.prim.req/type-requirement.cpp clang/test/CXX/temp/temp.constr/temp.constr.atomic/constrant-satisfaction-conversions.cpp clang/test/CXX/temp/temp.constr/temp.constr.normal/p1.cpp clang/test/CXX/temp/temp.param/p10-2a.cpp clang/test/SemaCXX/cxx23-assume.cpp clang/test/SemaCXX/cxx2b-deducing-this.cpp clang/test/SemaCXX/cxx2c-fold-exprs.cpp clang/test/SemaCXX/cxx2c-template-template-param.cpp clang/test/SemaCXX/invalid-requirement-requires-expr.cpp clang/test/SemaCXX/overload-resolution-deferred-templates.cpp clang/test/SemaCXX/type-traits.cpp clang/test/SemaTemplate/concepts-recovery-expr.cpp clang/test/SemaTemplate/concepts-recursive-inst.cpp clang/test/SemaTemplate/concepts.cpp clang/test/SemaTemplate/deduction-guide.cpp clang/test/SemaTemplate/instantiate-abbreviated-template.cpp clang/test/SemaTemplate/instantiate-expanded-type-constraint.cpp clang/test/SemaTemplate/instantiate-requires-expr.cpp clang/test/SemaTemplate/instantiate-template-argument.cpp clang/test/SemaTemplate/pr52970.cpp libcxx/test/libcxx/algorithms/cpp17_iterator_concepts.verify.cpp
View the diff from clang-format here.diff --git a/clang/include/clang/Sema/SemaConcept.h b/clang/include/clang/Sema/SemaConcept.h
index 648a9c51a..df1d5a95d 100644
--- a/clang/include/clang/Sema/SemaConcept.h
+++ b/clang/include/clang/Sema/SemaConcept.h
@@ -77,15 +77,15 @@ struct NormalizedConstraint {
CompoundConstraint>
Constraint;
- NormalizedConstraint(AtomicConstraint *C): Constraint{C} { };
+ NormalizedConstraint(AtomicConstraint *C) : Constraint{C} {};
NormalizedConstraint(FoldExpandedConstraint *C) : Constraint{C} {};
NormalizedConstraint(ASTContext &C, NormalizedConstraint LHS,
NormalizedConstraint RHS, CompoundConstraintKind Kind);
NormalizedConstraint(ASTContext &C, const NormalizedConstraint &Other);
- NormalizedConstraint(NormalizedConstraint &&Other):
- Constraint(Other.Constraint) {
+ NormalizedConstraint(NormalizedConstraint &&Other)
+ : Constraint(Other.Constraint) {
Other.Constraint = nullptr;
}
NormalizedConstraint &operator=(const NormalizedConstraint &Other) = delete;
@@ -240,6 +240,6 @@ private:
uint16_t getNewLiteralId();
};
-} // clang
+} // namespace clang
#endif // LLVM_CLANG_SEMA_SEMACONCEPT_H
diff --git a/clang/lib/AST/ASTConcept.cpp b/clang/lib/AST/ASTConcept.cpp
index d658890e0..c4e88223c 100644
--- a/clang/lib/AST/ASTConcept.cpp
+++ b/clang/lib/AST/ASTConcept.cpp
@@ -74,9 +74,10 @@ ASTConstraintSatisfaction *ASTConstraintSatisfaction::Rebuild(
return new (Mem) ASTConstraintSatisfaction(C, Satisfaction);
}
-void ConstraintSatisfaction::Profile(
- llvm::FoldingSetNodeID &ID, const ASTContext &C,
- const NamedDecl *ConstraintOwner, ArrayRef<TemplateArgument> TemplateArgs) {
+void ConstraintSatisfaction::Profile(llvm::FoldingSetNodeID &ID,
+ const ASTContext &C,
+ const NamedDecl *ConstraintOwner,
+ ArrayRef<TemplateArgument> TemplateArgs) {
ID.AddPointer(ConstraintOwner);
ID.AddInteger(TemplateArgs.size());
for (auto &Arg : TemplateArgs)
diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index dc6d232d9..db2e596c1 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -85,7 +85,7 @@ public:
OK_Ordinary, Loc, FPOptionsOverride{});
}
};
-}
+} // namespace
bool Sema::CheckConstraintExpression(const Expr *ConstraintExpression,
Token NextToken, bool *PossibleNonPrimary,
@@ -146,14 +146,14 @@ bool Sema::CheckConstraintExpression(const Expr *ConstraintExpression,
if (!Context.hasSameUnqualifiedType(Type, Context.BoolTy)) {
Diag(ConstraintExpression->getExprLoc(),
- diag::err_non_bool_atomic_constraint) << Type
- << ConstraintExpression->getSourceRange();
+ diag::err_non_bool_atomic_constraint)
+ << Type << ConstraintExpression->getSourceRange();
CheckForNonPrimary();
return false;
}
if (PossibleNonPrimary)
- *PossibleNonPrimary = false;
+ *PossibleNonPrimary = false;
return true;
}
@@ -164,14 +164,14 @@ struct SatisfactionStackRAII {
SatisfactionStackRAII(Sema &SemaRef, const NamedDecl *ND,
const llvm::FoldingSetNodeID &FSNID)
: SemaRef(SemaRef) {
- if (ND) {
+ if (ND) {
SemaRef.PushSatisfactionStackEntry(ND, FSNID);
Inserted = true;
- }
+ }
}
~SatisfactionStackRAII() {
- if (Inserted)
- SemaRef.PopSatisfactionStackEntry();
+ if (Inserted)
+ SemaRef.PopSatisfactionStackEntry();
}
};
} // namespace
@@ -582,7 +582,8 @@ static bool CheckConstraintSatisfaction(
TemplateArgsLists.getNumSubstitutedLevels() > 0
? TemplateArgsLists.getOutermost()
: ArrayRef<TemplateArgument>{};
- Sema::InstantiatingTemplate Inst(S, TemplateIDRange.getBegin(),
+ Sema::InstantiatingTemplate Inst(
+ S, TemplateIDRange.getBegin(),
Sema::InstantiatingTemplate::ConstraintsCheck{},
const_cast<NamedDecl *>(Template), TemplateArgs, TemplateIDRange);
if (Inst.isInvalid())
@@ -854,7 +855,6 @@ bool Sema::CheckFunctionConstraints(const FunctionDecl *FD,
Satisfaction);
}
-
// Figure out the to-translation-unit depth for this function declaration for
// the purpose of seeing if they differ by constraints. This isn't the same as
// getTemplateDepth, because it includes already instantiated parents.
@@ -871,9 +871,10 @@ CalculateTemplateDepthForConstraints(Sema &S, const NamedDecl *ND,
}
namespace {
- class AdjustConstraintDepth : public TreeTransform<AdjustConstraintDepth> {
+class AdjustConstraintDepth : public TreeTransform<AdjustConstraintDepth> {
unsigned TemplateDepth = 0;
- public:
+
+public:
using inherited = TreeTransform<AdjustConstraintDepth>;
AdjustConstraintDepth(Sema &SemaRef, unsigned TemplateDepth)
: inherited(SemaRef), TemplateDepth(TemplateDepth) {}
@@ -895,7 +896,7 @@ namespace {
NewTL.setNameLoc(TL.getNameLoc());
return Result;
}
- };
+};
} // namespace
static const Expr *SubstituteConstraintExpressionWithoutSatisfaction(
@@ -1161,73 +1162,74 @@ bool Sema::CheckFunctionTemplateConstraints(
static void diagnoseUnsatisfiedRequirement(Sema &S,
concepts::ExprRequirement *Req,
bool First) {
- assert(!Req->isSatisfied()
- && "Diagnose() can only be used on an unsatisfied requirement");
+ assert(!Req->isSatisfied() &&
+ "Diagnose() can only be used on an unsatisfied requirement");
switch (Req->getSatisfactionStatus()) {
- case concepts::ExprRequirement::SS_Dependent:
- llvm_unreachable("Diagnosing a dependent requirement");
- break;
- case concepts::ExprRequirement::SS_ExprSubstitutionFailure: {
- auto *SubstDiag = Req->getExprSubstitutionDiagnostic();
- if (!SubstDiag->DiagMessage.empty())
- S.Diag(SubstDiag->DiagLoc,
- diag::note_expr_requirement_expr_substitution_error)
- << (int)First << SubstDiag->SubstitutedEntity
- << SubstDiag->DiagMessage;
- else
- S.Diag(SubstDiag->DiagLoc,
- diag::note_expr_requirement_expr_unknown_substitution_error)
- << (int)First << SubstDiag->SubstitutedEntity;
- break;
- }
- case concepts::ExprRequirement::SS_NoexceptNotMet:
- S.Diag(Req->getNoexceptLoc(),
- diag::note_expr_requirement_noexcept_not_met)
- << (int)First << Req->getExpr();
- break;
- case concepts::ExprRequirement::SS_TypeRequirementSubstitutionFailure: {
- auto *SubstDiag =
- Req->getReturnTypeRequirement().getSubstitutionDiagnostic();
- if (!SubstDiag->DiagMessage.empty())
- S.Diag(SubstDiag->DiagLoc,
- diag::note_expr_requirement_type_requirement_substitution_error)
- << (int)First << SubstDiag->SubstitutedEntity
- << SubstDiag->DiagMessage;
- else
- S.Diag(SubstDiag->DiagLoc,
- diag::note_expr_requirement_type_requirement_unknown_substitution_error)
- << (int)First << SubstDiag->SubstitutedEntity;
- break;
- }
- case concepts::ExprRequirement::SS_ConstraintsNotSatisfied: {
- ConceptSpecializationExpr *ConstraintExpr =
- Req->getReturnTypeRequirementSubstitutedConstraintExpr();
- if (ConstraintExpr->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
- // A simple case - expr type is the type being constrained and the concept
- // was not provided arguments.
- Expr *e = Req->getExpr();
- S.Diag(e->getBeginLoc(),
- diag::note_expr_requirement_constraints_not_satisfied_simple)
- << (int)First << S.Context.getReferenceQualifiedType(e)
- << ConstraintExpr->getNamedConcept();
- } else {
- S.Diag(ConstraintExpr->getBeginLoc(),
- diag::note_expr_requirement_constraints_not_satisfied)
- << (int)First << ConstraintExpr;
- }
- S.DiagnoseUnsatisfiedConstraint(ConstraintExpr->getSatisfaction());
- break;
+ case concepts::ExprRequirement::SS_Dependent:
+ llvm_unreachable("Diagnosing a dependent requirement");
+ break;
+ case concepts::ExprRequirement::SS_ExprSubstitutionFailure: {
+ auto *SubstDiag = Req->getExprSubstitutionDiagnostic();
+ if (!SubstDiag->DiagMessage.empty())
+ S.Diag(SubstDiag->DiagLoc,
+ diag::note_expr_requirement_expr_substitution_error)
+ << (int)First << SubstDiag->SubstitutedEntity
+ << SubstDiag->DiagMessage;
+ else
+ S.Diag(SubstDiag->DiagLoc,
+ diag::note_expr_requirement_expr_unknown_substitution_error)
+ << (int)First << SubstDiag->SubstitutedEntity;
+ break;
+ }
+ case concepts::ExprRequirement::SS_NoexceptNotMet:
+ S.Diag(Req->getNoexceptLoc(), diag::note_expr_requirement_noexcept_not_met)
+ << (int)First << Req->getExpr();
+ break;
+ case concepts::ExprRequirement::SS_TypeRequirementSubstitutionFailure: {
+ auto *SubstDiag =
+ Req->getReturnTypeRequirement().getSubstitutionDiagnostic();
+ if (!SubstDiag->DiagMessage.empty())
+ S.Diag(SubstDiag->DiagLoc,
+ diag::note_expr_requirement_type_requirement_substitution_error)
+ << (int)First << SubstDiag->SubstitutedEntity
+ << SubstDiag->DiagMessage;
+ else
+ S.Diag(
+ SubstDiag->DiagLoc,
+ diag::
+ note_expr_requirement_type_requirement_unknown_substitution_error)
+ << (int)First << SubstDiag->SubstitutedEntity;
+ break;
+ }
+ case concepts::ExprRequirement::SS_ConstraintsNotSatisfied: {
+ ConceptSpecializationExpr *ConstraintExpr =
+ Req->getReturnTypeRequirementSubstitutedConstraintExpr();
+ if (ConstraintExpr->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
+ // A simple case - expr type is the type being constrained and the concept
+ // was not provided arguments.
+ Expr *e = Req->getExpr();
+ S.Diag(e->getBeginLoc(),
+ diag::note_expr_requirement_constraints_not_satisfied_simple)
+ << (int)First << S.Context.getReferenceQualifiedType(e)
+ << ConstraintExpr->getNamedConcept();
+ } else {
+ S.Diag(ConstraintExpr->getBeginLoc(),
+ diag::note_expr_requirement_constraints_not_satisfied)
+ << (int)First << ConstraintExpr;
}
- case concepts::ExprRequirement::SS_Satisfied:
- llvm_unreachable("We checked this above");
+ S.DiagnoseUnsatisfiedConstraint(ConstraintExpr->getSatisfaction());
+ break;
+ }
+ case concepts::ExprRequirement::SS_Satisfied:
+ llvm_unreachable("We checked this above");
}
}
static void diagnoseUnsatisfiedRequirement(Sema &S,
concepts::TypeRequirement *Req,
bool First) {
- assert(!Req->isSatisfied()
- && "Diagnose() can only be used on an unsatisfied requirement");
+ assert(!Req->isSatisfied() &&
+ "Diagnose() can only be used on an unsatisfied requirement");
switch (Req->getSatisfactionStatus()) {
case concepts::TypeRequirement::SS_Dependent:
llvm_unreachable("Diagnosing a dependent requirement");
@@ -1235,9 +1237,9 @@ static void diagnoseUnsatisfiedRequirement(Sema &S,
case concepts::TypeRequirement::SS_SubstitutionFailure: {
auto *SubstDiag = Req->getSubstitutionDiagnostic();
if (!SubstDiag->DiagMessage.empty())
- S.Diag(SubstDiag->DiagLoc,
- diag::note_type_requirement_substitution_error) << (int)First
- << SubstDiag->SubstitutedEntity << SubstDiag->DiagMessage;
+ S.Diag(SubstDiag->DiagLoc, diag::note_type_requirement_substitution_error)
+ << (int)First << SubstDiag->SubstitutedEntity
+ << SubstDiag->DiagMessage;
else
S.Diag(SubstDiag->DiagLoc,
diag::note_type_requirement_unknown_substitution_error)
@@ -1319,7 +1321,7 @@ static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S,
BO->getRHS()->EvaluateAsInt(SimplifiedRHS, S.Context,
Expr::SE_NoSideEffects,
/*InConstantContext=*/true);
- if (!SimplifiedLHS.Diag && ! SimplifiedRHS.Diag) {
+ if (!SimplifiedLHS.Diag && !SimplifiedRHS.Diag) {
S.Diag(SubstExpr->getBeginLoc(),
diag::note_atomic_constraint_evaluated_to_false_elaborated)
<< (int)First << SubstExpr
@@ -1339,7 +1341,7 @@ static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S,
S.Diag(
CSE->getSourceRange().getBegin(),
diag::
- note_single_arg_concept_specialization_constraint_evaluated_to_false)
+ note_single_arg_concept_specialization_constraint_evaluated_to_false)
<< (int)First
<< CSE->getTemplateArgsAsWritten()->arguments()[0].getArgument()
<< CSE->getNamedConcept();
@@ -1392,9 +1394,8 @@ static void diagnoseUnsatisfiedConstraintExpr(
diagnoseWellFormedUnsatisfiedConstraintExpr(S, cast<Expr *>(Record), First);
}
-void
-Sema::DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction& Satisfaction,
- bool First) {
+void Sema::DiagnoseUnsatisfiedConstraint(
+ const ConstraintSatisfaction &Satisfaction, bool First) {
assert(!Satisfaction.IsSatisfied &&
"Attempted to diagnose a satisfied constraint");
for (auto &Record : Satisfaction.Details) {
@@ -1404,8 +1405,7 @@ Sema::DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction& Satisfaction,
}
void Sema::DiagnoseUnsatisfiedConstraint(
- const ASTConstraintSatisfaction &Satisfaction,
- bool First) {
+ const ASTConstraintSatisfaction &Satisfaction, bool First) {
assert(!Satisfaction.IsSatisfied &&
"Attempted to diagnose a satisfied constraint");
for (auto &Record : Satisfaction) {
@@ -1430,8 +1430,8 @@ const NormalizedConstraint *Sema::getNormalizedAssociatedConstraints(
NormalizationCache
.try_emplace(ConstrainedDecl,
Normalized
- ? new (Context) NormalizedConstraint(
- std::move(*Normalized))
+ ? new (Context)
+ NormalizedConstraint(std::move(*Normalized))
: nullptr)
.first;
}
@@ -1492,7 +1492,7 @@ substituteParameterMappings(Sema &S, NormalizedConstraint &N,
ArgsAsWritten->NumTemplateArgs > I
? ArgsAsWritten->arguments()[I].getLocation()
: SourceLocation()));
- Atomic.ParameterMapping.emplace(TempArgs, OccurringIndices.count());
+ Atomic.ParameterMapping.emplace(TempArgs, OccurringIndices.count());
}
SourceLocation InstLocBegin =
ArgsAsWritten->arguments().empty()
@@ -1538,7 +1538,7 @@ NormalizedConstraint::NormalizedConstraint(ASTContext &C,
NormalizedConstraint RHS,
CompoundConstraintKind Kind)
: Constraint{CompoundConstraint{
- new(C) NormalizedConstraintPair{std::move(LHS), std::move(RHS)},
+ new (C) NormalizedConstraintPair{std::move(LHS), std::move(RHS)},
Kind}} {}
NormalizedConstraint::NormalizedConstraint(ASTContext &C,
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 2bf1511c5..86af11749 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -4850,13 +4850,10 @@ void Sema::diagnoseMissingTemplateArguments(const CXXScopeSpec &SS,
diagnoseMissingTemplateArguments(Name, Loc);
}
-ExprResult
-Sema::CheckConceptTemplateId(const CXXScopeSpec &SS,
- SourceLocation TemplateKWLoc,
- const DeclarationNameInfo &ConceptNameInfo,
- NamedDecl *FoundDecl,
- ConceptDecl *NamedConcept,
- const TemplateArgumentListInfo *TemplateArgs) {
+ExprResult Sema::CheckConceptTemplateId(
+ const CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
+ const DeclarationNameInfo &ConceptNameInfo, NamedDecl *FoundDecl,
+ ConceptDecl *NamedConcept, const TemplateArgumentListInfo *TemplateArgs) {
assert(NamedConcept && "A concept template id without a template?");
if (NamedConcept->isInvalidDecl())
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index f6ee7452c..421fcf5d6 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -6677,9 +6677,8 @@ struct MarkUsedTemplateParameterVisitor : DynamicRecursiveASTVisitor {
llvm::SmallBitVector &Used;
unsigned Depth;
- MarkUsedTemplateParameterVisitor(llvm::SmallBitVector &Used,
- unsigned Depth)
- : Used(Used), Depth(Depth) { }
+ MarkUsedTemplateParameterVisitor(llvm::SmallBitVector &Used, unsigned Depth)
+ : Used(Used), Depth(Depth) {}
bool VisitTemplateTypeParmType(TemplateTypeParmType *T) override {
if (T->getDepth() == Depth)
@@ -7044,9 +7043,9 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T,
case Type::UnaryTransform:
if (!OnlyDeduced)
- MarkUsedTemplateParameters(Ctx,
- cast<UnaryTransformType>(T)->getUnderlyingType(),
- OnlyDeduced, Depth, Used);
+ MarkUsedTemplateParameters(
+ Ctx, cast<UnaryTransformType>(T)->getUnderlyingType(), OnlyDeduced,
+ Depth, Used);
break;
case Type::PackExpansion:
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index f1c9c5c86..b68a6d123 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -1375,543 +1375,541 @@ std::optional<TemplateDeductionInfo *> Sema::isSFINAEContext() const {
// Template Instantiation for Types
//===----------------------------------------------------------------------===/
namespace {
- class TemplateInstantiator : public TreeTransform<TemplateInstantiator> {
- const MultiLevelTemplateArgumentList &TemplateArgs;
- SourceLocation Loc;
- DeclarationName Entity;
- // Whether to evaluate the C++20 constraints or simply substitute into them.
- bool EvaluateConstraints = true;
- // Whether Substitution was Incomplete, that is, we tried to substitute in
- // any user provided template arguments which were null.
- bool IsIncomplete = false;
- // Whether an incomplete substituion should be treated as an error.
- bool BailOutOnIncomplete;
-
- private:
- // CWG2770: Function parameters should be instantiated when they are
- // needed by a satisfaction check of an atomic constraint or
- // (recursively) by another function parameter.
- bool maybeInstantiateFunctionParameterToScope(ParmVarDecl *OldParm);
-
- public:
- typedef TreeTransform<TemplateInstantiator> inherited;
-
- TemplateInstantiator(Sema &SemaRef,
- const MultiLevelTemplateArgumentList &TemplateArgs,
- SourceLocation Loc, DeclarationName Entity,
- bool BailOutOnIncomplete = false)
- : inherited(SemaRef), TemplateArgs(TemplateArgs), Loc(Loc),
- Entity(Entity), BailOutOnIncomplete(BailOutOnIncomplete) {}
-
- void setEvaluateConstraints(bool B) {
- EvaluateConstraints = B;
- }
- bool getEvaluateConstraints() {
- return EvaluateConstraints;
- }
-
- /// Determine whether the given type \p T has already been
- /// transformed.
- ///
- /// For the purposes of template instantiation, a type has already been
- /// transformed if it is NULL or if it is not dependent.
- bool AlreadyTransformed(QualType T);
+class TemplateInstantiator : public TreeTransform<TemplateInstantiator> {
+ const MultiLevelTemplateArgumentList &TemplateArgs;
+ SourceLocation Loc;
+ DeclarationName Entity;
+ // Whether to evaluate the C++20 constraints or simply substitute into them.
+ bool EvaluateConstraints = true;
+ // Whether Substitution was Incomplete, that is, we tried to substitute in
+ // any user provided template arguments which were null.
+ bool IsIncomplete = false;
+ // Whether an incomplete substituion should be treated as an error.
+ bool BailOutOnIncomplete;
+
+private:
+ // CWG2770: Function parameters should be instantiated when they are
+ // needed by a satisfaction check of an atomic constraint or
+ // (recursively) by another function parameter.
+ bool maybeInstantiateFunctionParameterToScope(ParmVarDecl *OldParm);
+
+public:
+ typedef TreeTransform<TemplateInstantiator> inherited;
+
+ TemplateInstantiator(Sema &SemaRef,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ SourceLocation Loc, DeclarationName Entity,
+ bool BailOutOnIncomplete = false)
+ : inherited(SemaRef), TemplateArgs(TemplateArgs), Loc(Loc),
+ Entity(Entity), BailOutOnIncomplete(BailOutOnIncomplete) {}
+
+ void setEvaluateConstraints(bool B) { EvaluateConstraints = B; }
+ bool getEvaluateConstraints() { return EvaluateConstraints; }
+
+ /// Determine whether the given type \p T has already been
+ /// transformed.
+ ///
+ /// For the purposes of template instantiation, a type has already been
+ /// transformed if it is NULL or if it is not dependent.
+ bool AlreadyTransformed(QualType T);
+
+ /// Returns the location of the entity being instantiated, if known.
+ SourceLocation getBaseLocation() { return Loc; }
+
+ /// Returns the name of the entity being instantiated, if any.
+ DeclarationName getBaseEntity() { return Entity; }
+
+ /// Returns whether any substitution so far was incomplete.
+ bool getIsIncomplete() const { return IsIncomplete; }
+
+ /// Sets the "base" location and entity when that
+ /// information is known based on another transformation.
+ void setBase(SourceLocation Loc, DeclarationName Entity) {
+ this->Loc = Loc;
+ this->Entity = Entity;
+ }
- /// Returns the location of the entity being instantiated, if known.
- SourceLocation getBaseLocation() { return Loc; }
+ unsigned TransformTemplateDepth(unsigned Depth) {
+ return TemplateArgs.getNewDepth(Depth);
+ }
- /// Returns the name of the entity being instantiated, if any.
- DeclarationName getBaseEntity() { return Entity; }
+ bool TryExpandParameterPacks(SourceLocation EllipsisLoc,
+ SourceRange PatternRange,
+ ArrayRef<UnexpandedParameterPack> Unexpanded,
+ bool FailOnPackProducingTemplates,
+ bool &ShouldExpand, bool &RetainExpansion,
+ UnsignedOrNone &NumExpansions) {
+ if (SemaRef.CurrentInstantiationScope &&
+ SemaRef.inConstraintSubstitution()) {
+ for (UnexpandedParameterPack ParmPack : Unexpanded) {
+ NamedDecl *VD = ParmPack.first.dyn_cast<NamedDecl *>();
+ if (auto *PVD = dyn_cast_if_present<ParmVarDecl>(VD);
+ PVD && maybeInstantiateFunctionParameterToScope(PVD))
+ return true;
+ }
+ }
- /// Returns whether any substitution so far was incomplete.
- bool getIsIncomplete() const { return IsIncomplete; }
+ return getSema().CheckParameterPacksForExpansion(
+ EllipsisLoc, PatternRange, Unexpanded, TemplateArgs,
+ FailOnPackProducingTemplates, ShouldExpand, RetainExpansion,
+ NumExpansions);
+ }
- /// Sets the "base" location and entity when that
- /// information is known based on another transformation.
- void setBase(SourceLocation Loc, DeclarationName Entity) {
- this->Loc = Loc;
- this->Entity = Entity;
- }
+ void ExpandingFunctionParameterPack(ParmVarDecl *Pack) {
+ SemaRef.CurrentInstantiationScope->MakeInstantiatedLocalArgPack(Pack);
+ }
- unsigned TransformTemplateDepth(unsigned Depth) {
- return TemplateArgs.getNewDepth(Depth);
+ TemplateArgument ForgetPartiallySubstitutedPack() {
+ TemplateArgument Result;
+ if (NamedDecl *PartialPack =
+ SemaRef.CurrentInstantiationScope->getPartiallySubstitutedPack()) {
+ MultiLevelTemplateArgumentList &TemplateArgs =
+ const_cast<MultiLevelTemplateArgumentList &>(this->TemplateArgs);
+ unsigned Depth, Index;
+ std::tie(Depth, Index) = getDepthAndIndex(PartialPack);
+ if (TemplateArgs.hasTemplateArgument(Depth, Index)) {
+ Result = TemplateArgs(Depth, Index);
+ TemplateArgs.setArgument(Depth, Index, TemplateArgument());
+ } else {
+ IsIncomplete = true;
+ if (BailOutOnIncomplete)
+ return TemplateArgument();
+ }
}
- bool TryExpandParameterPacks(SourceLocation EllipsisLoc,
- SourceRange PatternRange,
- ArrayRef<UnexpandedParameterPack> Unexpanded,
- bool FailOnPackProducingTemplates,
- bool &ShouldExpand, bool &RetainExpansion,
- UnsignedOrNone &NumExpansions) {
- if (SemaRef.CurrentInstantiationScope &&
- SemaRef.inConstraintSubstitution()) {
- for (UnexpandedParameterPack ParmPack : Unexpanded) {
- NamedDecl *VD = ParmPack.first.dyn_cast<NamedDecl *>();
- if (auto *PVD = dyn_cast_if_present<ParmVarDecl>(VD);
- PVD && maybeInstantiateFunctionParameterToScope(PVD))
- return true;
- }
- }
+ return Result;
+ }
- return getSema().CheckParameterPacksForExpansion(
- EllipsisLoc, PatternRange, Unexpanded, TemplateArgs,
- FailOnPackProducingTemplates, ShouldExpand, RetainExpansion,
- NumExpansions);
- }
+ void RememberPartiallySubstitutedPack(TemplateArgument Arg) {
+ if (Arg.isNull())
+ return;
- void ExpandingFunctionParameterPack(ParmVarDecl *Pack) {
- SemaRef.CurrentInstantiationScope->MakeInstantiatedLocalArgPack(Pack);
+ if (NamedDecl *PartialPack =
+ SemaRef.CurrentInstantiationScope->getPartiallySubstitutedPack()) {
+ MultiLevelTemplateArgumentList &TemplateArgs =
+ const_cast<MultiLevelTemplateArgumentList &>(this->TemplateArgs);
+ unsigned Depth, Index;
+ std::tie(Depth, Index) = getDepthAndIndex(PartialPack);
+ TemplateArgs.setArgument(Depth, Index, Arg);
}
+ }
- TemplateArgument ForgetPartiallySubstitutedPack() {
- TemplateArgument Result;
- if (NamedDecl *PartialPack
- = SemaRef.CurrentInstantiationScope->getPartiallySubstitutedPack()){
- MultiLevelTemplateArgumentList &TemplateArgs
- = const_cast<MultiLevelTemplateArgumentList &>(this->TemplateArgs);
- unsigned Depth, Index;
- std::tie(Depth, Index) = getDepthAndIndex(PartialPack);
- if (TemplateArgs.hasTemplateArgument(Depth, Index)) {
- Result = TemplateArgs(Depth, Index);
- TemplateArgs.setArgument(Depth, Index, TemplateArgument());
- } else {
- IsIncomplete = true;
- if (BailOutOnIncomplete)
- return TemplateArgument();
- }
- }
+ MultiLevelTemplateArgumentList ForgetSubstitution() {
+ MultiLevelTemplateArgumentList New;
+ New.addOuterRetainedLevels(this->TemplateArgs.getNumLevels());
- return Result;
- }
+ MultiLevelTemplateArgumentList Old =
+ const_cast<MultiLevelTemplateArgumentList &>(this->TemplateArgs);
+ const_cast<MultiLevelTemplateArgumentList &>(this->TemplateArgs) =
+ std::move(New);
+ return Old;
+ }
+ void RememberSubstitution(MultiLevelTemplateArgumentList Old) {
+ const_cast<MultiLevelTemplateArgumentList &>(this->TemplateArgs) =
+ std::move(Old);
+ }
- void RememberPartiallySubstitutedPack(TemplateArgument Arg) {
- if (Arg.isNull())
- return;
-
- if (NamedDecl *PartialPack
- = SemaRef.CurrentInstantiationScope->getPartiallySubstitutedPack()){
- MultiLevelTemplateArgumentList &TemplateArgs
- = const_cast<MultiLevelTemplateArgumentList &>(this->TemplateArgs);
- unsigned Depth, Index;
- std::tie(Depth, Index) = getDepthAndIndex(PartialPack);
- TemplateArgs.setArgument(Depth, Index, Arg);
- }
- }
+ TemplateArgument
+ getTemplateArgumentPackPatternForRewrite(const TemplateArgument &TA) {
+ if (TA.getKind() != TemplateArgument::Pack)
+ return TA;
+ if (SemaRef.ArgPackSubstIndex)
+ return SemaRef.getPackSubstitutedTemplateArgument(TA);
+ assert(TA.pack_size() == 1 && TA.pack_begin()->isPackExpansion() &&
+ "unexpected pack arguments in template rewrite");
+ TemplateArgument Arg = *TA.pack_begin();
+ if (Arg.isPackExpansion())
+ Arg = Arg.getPackExpansionPattern();
+ return Arg;
+ }
- MultiLevelTemplateArgumentList ForgetSubstitution() {
- MultiLevelTemplateArgumentList New;
- New.addOuterRetainedLevels(this->TemplateArgs.getNumLevels());
+ /// Transform the given declaration by instantiating a reference to
+ /// this declaration.
+ Decl *TransformDecl(SourceLocation Loc, Decl *D);
- MultiLevelTemplateArgumentList Old =
- const_cast<MultiLevelTemplateArgumentList &>(this->TemplateArgs);
- const_cast<MultiLevelTemplateArgumentList &>(this->TemplateArgs) =
- std::move(New);
- return Old;
- }
- void RememberSubstitution(MultiLevelTemplateArgumentList Old) {
- const_cast<MultiLevelTemplateArgumentList &>(this->TemplateArgs) =
- std::move(Old);
- }
+ void transformAttrs(Decl *Old, Decl *New) {
+ SemaRef.InstantiateAttrs(TemplateArgs, Old, New);
+ }
- TemplateArgument
- getTemplateArgumentPackPatternForRewrite(const TemplateArgument &TA) {
- if (TA.getKind() != TemplateArgument::Pack)
- return TA;
- if (SemaRef.ArgPackSubstIndex)
- return SemaRef.getPackSubstitutedTemplateArgument(TA);
- assert(TA.pack_size() == 1 && TA.pack_begin()->isPackExpansion() &&
- "unexpected pack arguments in template rewrite");
- TemplateArgument Arg = *TA.pack_begin();
- if (Arg.isPackExpansion())
- Arg = Arg.getPackExpansionPattern();
- return Arg;
+ void transformedLocalDecl(Decl *Old, ArrayRef<Decl *> NewDecls) {
+ if (Old->isParameterPack() &&
+ (NewDecls.size() != 1 || !NewDecls.front()->isParameterPack())) {
+ SemaRef.CurrentInstantiationScope->MakeInstantiatedLocalArgPack(Old);
+ for (auto *New : NewDecls)
+ SemaRef.CurrentInstantiationScope->InstantiatedLocalPackArg(
+ Old, cast<VarDecl>(New));
+ return;
}
- /// Transform the given declaration by instantiating a reference to
- /// this declaration.
- Decl *TransformDecl(SourceLocation Loc, Decl *D);
-
- void transformAttrs(Decl *Old, Decl *New) {
- SemaRef.InstantiateAttrs(TemplateArgs, Old, New);
+ assert(NewDecls.size() == 1 &&
+ "should only have multiple expansions for a pack");
+ Decl *New = NewDecls.front();
+
+ // If we've instantiated the call operator of a lambda or the call
+ // operator template of a generic lambda, update the "instantiation of"
+ // information.
+ auto *NewMD = dyn_cast<CXXMethodDecl>(New);
+ if (NewMD && isLambdaCallOperator(NewMD)) {
+ auto *OldMD = dyn_cast<CXXMethodDecl>(Old);
+ if (auto *NewTD = NewMD->getDescribedFunctionTemplate())
+ NewTD->setInstantiatedFromMemberTemplate(
+ OldMD->getDescribedFunctionTemplate());
+ else
+ NewMD->setInstantiationOfMemberFunction(OldMD,
+ TSK_ImplicitInstantiation);
}
- void transformedLocalDecl(Decl *Old, ArrayRef<Decl *> NewDecls) {
- if (Old->isParameterPack() &&
- (NewDecls.size() != 1 || !NewDecls.front()->isParameterPack())) {
- SemaRef.CurrentInstantiationScope->MakeInstantiatedLocalArgPack(Old);
- for (auto *New : NewDecls)
- SemaRef.CurrentInstantiationScope->InstantiatedLocalPackArg(
- Old, cast<VarDecl>(New));
- return;
- }
+ SemaRef.CurrentInstantiationScope->InstantiatedLocal(Old, New);
- assert(NewDecls.size() == 1 &&
- "should only have multiple expansions for a pack");
- Decl *New = NewDecls.front();
-
- // If we've instantiated the call operator of a lambda or the call
- // operator template of a generic lambda, update the "instantiation of"
- // information.
- auto *NewMD = dyn_cast<CXXMethodDecl>(New);
- if (NewMD && isLambdaCallOperator(NewMD)) {
- auto *OldMD = dyn_cast<CXXMethodDecl>(Old);
- if (auto *NewTD = NewMD->getDescribedFunctionTemplate())
- NewTD->setInstantiatedFromMemberTemplate(
- OldMD->getDescribedFunctionTemplate());
- else
- NewMD->setInstantiationOfMemberFunction(OldMD,
- TSK_ImplicitInstantiation);
- }
+ // We recreated a local declaration, but not by instantiating it. There
+ // may be pending dependent diagnostics to produce.
+ if (auto *DC = dyn_cast<DeclContext>(Old);
+ DC && DC->isDependentContext() && DC->isFunctionOrMethod())
+ SemaRef.PerformDependentDiagnostics(DC, TemplateArgs);
+ }
- SemaRef.CurrentInstantiationScope->InstantiatedLocal(Old, New);
+ /// Transform the definition of the given declaration by
+ /// instantiating it.
+ Decl *TransformDefinition(SourceLocation Loc, Decl *D);
- // We recreated a local declaration, but not by instantiating it. There
- // may be pending dependent diagnostics to produce.
- if (auto *DC = dyn_cast<DeclContext>(Old);
- DC && DC->isDependentContext() && DC->isFunctionOrMethod())
- SemaRef.PerformDependentDiagnostics(DC, TemplateArgs);
- }
+ /// Transform the first qualifier within a scope by instantiating the
+ /// declaration.
+ NamedDecl *TransformFirstQualifierInScope(NamedDecl *D, SourceLocation Loc);
- /// Transform the definition of the given declaration by
- /// instantiating it.
- Decl *TransformDefinition(SourceLocation Loc, Decl *D);
-
- /// Transform the first qualifier within a scope by instantiating the
- /// declaration.
- NamedDecl *TransformFirstQualifierInScope(NamedDecl *D, SourceLocation Loc);
-
- bool TransformExceptionSpec(SourceLocation Loc,
- FunctionProtoType::ExceptionSpecInfo &ESI,
- SmallVectorImpl<QualType> &Exceptions,
- bool &Changed);
-
- /// Rebuild the exception declaration and register the declaration
- /// as an instantiated local.
- VarDecl *RebuildExceptionDecl(VarDecl *ExceptionDecl,
- TypeSourceInfo *Declarator,
- SourceLocation StartLoc,
- SourceLocation NameLoc,
- IdentifierInfo *Name);
-
- /// Rebuild the Objective-C exception declaration and register the
- /// declaration as an instantiated local.
- VarDecl *RebuildObjCExceptionDecl(VarDecl *ExceptionDecl,
- TypeSourceInfo *TSInfo, QualType T);
-
- TemplateName
- TransformTemplateName(NestedNameSpecifierLoc &QualifierLoc,
- SourceLocation TemplateKWLoc, TemplateName Name,
- SourceLocation NameLoc,
- QualType ObjectType = QualType(),
- NamedDecl *FirstQualifierInScope = nullptr,
- bool AllowInjectedClassName = false);
-
- const AnnotateAttr *TransformAnnotateAttr(const AnnotateAttr *AA);
- const CXXAssumeAttr *TransformCXXAssumeAttr(const CXXAssumeAttr *AA);
- const LoopHintAttr *TransformLoopHintAttr(const LoopHintAttr *LH);
- const NoInlineAttr *TransformStmtNoInlineAttr(const Stmt *OrigS,
- const Stmt *InstS,
- const NoInlineAttr *A);
- const AlwaysInlineAttr *
- TransformStmtAlwaysInlineAttr(const Stmt *OrigS, const Stmt *InstS,
- const AlwaysInlineAttr *A);
- const CodeAlignAttr *TransformCodeAlignAttr(const CodeAlignAttr *CA);
- const OpenACCRoutineDeclAttr *
- TransformOpenACCRoutineDeclAttr(const OpenACCRoutineDeclAttr *A);
- ExprResult TransformPredefinedExpr(PredefinedExpr *E);
- ExprResult TransformDeclRefExpr(DeclRefExpr *E);
- ExprResult TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E);
-
- ExprResult TransformTemplateParmRefExpr(DeclRefExpr *E,
- NonTypeTemplateParmDecl *D);
-
- /// Rebuild a DeclRefExpr for a VarDecl reference.
- ExprResult RebuildVarDeclRefExpr(ValueDecl *PD, SourceLocation Loc);
-
- /// Transform a reference to a function or init-capture parameter pack.
- ExprResult TransformFunctionParmPackRefExpr(DeclRefExpr *E, ValueDecl *PD);
-
- /// Transform a FunctionParmPackExpr which was built when we couldn't
- /// expand a function parameter pack reference which refers to an expanded
- /// pack.
- ExprResult TransformFunctionParmPackExpr(FunctionParmPackExpr *E);
-
- QualType TransformFunctionProtoType(TypeLocBuilder &TLB,
- FunctionProtoTypeLoc TL) {
- // Call the base version; it will forward to our overridden version below.
- return inherited::TransformFunctionProtoType(TLB, TL);
- }
+ bool TransformExceptionSpec(SourceLocation Loc,
+ FunctionProtoType::ExceptionSpecInfo &ESI,
+ SmallVectorImpl<QualType> &Exceptions,
+ bool &Changed);
+
+ /// Rebuild the exception declaration and register the declaration
+ /// as an instantiated local.
+ VarDecl *RebuildExceptionDecl(VarDecl *ExceptionDecl,
+ TypeSourceInfo *Declarator,
+ SourceLocation StartLoc, SourceLocation NameLoc,
+ IdentifierInfo *Name);
+
+ /// Rebuild the Objective-C exception declaration and register the
+ /// declaration as an instantiated local.
+ VarDecl *RebuildObjCExceptionDecl(VarDecl *ExceptionDecl,
+ TypeSourceInfo *TSInfo, QualType T);
+
+ TemplateName TransformTemplateName(NestedNameSpecifierLoc &QualifierLoc,
+ SourceLocation TemplateKWLoc,
+ TemplateName Name, SourceLocation NameLoc,
+ QualType ObjectType = QualType(),
+ NamedDecl *FirstQualifierInScope = nullptr,
+ bool AllowInjectedClassName = false);
+
+ const AnnotateAttr *TransformAnnotateAttr(const AnnotateAttr *AA);
+ const CXXAssumeAttr *TransformCXXAssumeAttr(const CXXAssumeAttr *AA);
+ const LoopHintAttr *TransformLoopHintAttr(const LoopHintAttr *LH);
+ const NoInlineAttr *TransformStmtNoInlineAttr(const Stmt *OrigS,
+ const Stmt *InstS,
+ const NoInlineAttr *A);
+ const AlwaysInlineAttr *
+ TransformStmtAlwaysInlineAttr(const Stmt *OrigS, const Stmt *InstS,
+ const AlwaysInlineAttr *A);
+ const CodeAlignAttr *TransformCodeAlignAttr(const CodeAlignAttr *CA);
+ const OpenACCRoutineDeclAttr *
+ TransformOpenACCRoutineDeclAttr(const OpenACCRoutineDeclAttr *A);
+ ExprResult TransformPredefinedExpr(PredefinedExpr *E);
+ ExprResult TransformDeclRefExpr(DeclRefExpr *E);
+ ExprResult TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E);
+
+ ExprResult TransformTemplateParmRefExpr(DeclRefExpr *E,
+ NonTypeTemplateParmDecl *D);
+
+ /// Rebuild a DeclRefExpr for a VarDecl reference.
+ ExprResult RebuildVarDeclRefExpr(ValueDecl *PD, SourceLocation Loc);
+
+ /// Transform a reference to a function or init-capture parameter pack.
+ ExprResult TransformFunctionParmPackRefExpr(DeclRefExpr *E, ValueDecl *PD);
+
+ /// Transform a FunctionParmPackExpr which was built when we couldn't
+ /// expand a function parameter pack reference which refers to an expanded
+ /// pack.
+ ExprResult TransformFunctionParmPackExpr(FunctionParmPackExpr *E);
+
+ QualType TransformFunctionProtoType(TypeLocBuilder &TLB,
+ FunctionProtoTypeLoc TL) {
+ // Call the base version; it will forward to our overridden version below.
+ return inherited::TransformFunctionProtoType(TLB, TL);
+ }
- QualType TransformTagType(TypeLocBuilder &TLB, TagTypeLoc TL) {
- auto Type = inherited::TransformTagType(TLB, TL);
- if (!Type.isNull())
- return Type;
- // Special case for transforming a deduction guide, we return a
- // transformed TemplateSpecializationType.
- // FIXME: Why is this hack necessary?
- if (const auto *ICNT = dyn_cast<InjectedClassNameType>(TL.getTypePtr());
- ICNT && SemaRef.CodeSynthesisContexts.back().Kind ==
- Sema::CodeSynthesisContext::BuildingDeductionGuides) {
- Type = inherited::TransformType(
- ICNT->getOriginalDecl()->getCanonicalTemplateSpecializationType(
- SemaRef.Context));
- TLB.pushTrivial(SemaRef.Context, Type, TL.getNameLoc());
- }
+ QualType TransformTagType(TypeLocBuilder &TLB, TagTypeLoc TL) {
+ auto Type = inherited::TransformTagType(TLB, TL);
+ if (!Type.isNull())
return Type;
+ // Special case for transforming a deduction guide, we return a
+ // transformed TemplateSpecializationType.
+ // FIXME: Why is this hack necessary?
+ if (const auto *ICNT = dyn_cast<InjectedClassNameType>(TL.getTypePtr());
+ ICNT && SemaRef.CodeSynthesisContexts.back().Kind ==
+ Sema::CodeSynthesisContext::BuildingDeductionGuides) {
+ Type = inherited::TransformType(
+ ICNT->getOriginalDecl()->getCanonicalTemplateSpecializationType(
+ SemaRef.Context));
+ TLB.pushTrivial(SemaRef.Context, Type, TL.getNameLoc());
}
- // Override the default version to handle a rewrite-template-arg-pack case
- // for building a deduction guide.
- bool TransformTemplateArgument(const TemplateArgumentLoc &Input,
- TemplateArgumentLoc &Output,
- bool Uneval = false) {
- const TemplateArgument &Arg = Input.getArgument();
- std::vector<TemplateArgument> TArgs;
- switch (Arg.getKind()) {
- case TemplateArgument::Pack:
- assert(SemaRef.CodeSynthesisContexts.empty() ||
- SemaRef.CodeSynthesisContexts.back().Kind ==
- Sema::CodeSynthesisContext::BuildingDeductionGuides);
- // Literally rewrite the template argument pack, instead of unpacking
- // it.
- for (auto &pack : Arg.getPackAsArray()) {
- TemplateArgumentLoc Input = SemaRef.getTrivialTemplateArgumentLoc(
- pack, QualType(), SourceLocation{});
- TemplateArgumentLoc Output;
- if (TransformTemplateArgument(Input, Output, Uneval))
- return true; // fails
- TArgs.push_back(Output.getArgument());
- }
- Output = SemaRef.getTrivialTemplateArgumentLoc(
- TemplateArgument(llvm::ArrayRef(TArgs).copy(SemaRef.Context)),
- QualType(), SourceLocation{});
- return false;
- default:
- break;
+ return Type;
+ }
+ // Override the default version to handle a rewrite-template-arg-pack case
+ // for building a deduction guide.
+ bool TransformTemplateArgument(const TemplateArgumentLoc &Input,
+ TemplateArgumentLoc &Output,
+ bool Uneval = false) {
+ const TemplateArgument &Arg = Input.getArgument();
+ std::vector<TemplateArgument> TArgs;
+ switch (Arg.getKind()) {
+ case TemplateArgument::Pack:
+ assert(SemaRef.CodeSynthesisContexts.empty() ||
+ SemaRef.CodeSynthesisContexts.back().Kind ==
+ Sema::CodeSynthesisContext::BuildingDeductionGuides);
+ // Literally rewrite the template argument pack, instead of unpacking
+ // it.
+ for (auto &pack : Arg.getPackAsArray()) {
+ TemplateArgumentLoc Input = SemaRef.getTrivialTemplateArgumentLoc(
+ pack, QualType(), SourceLocation{});
+ TemplateArgumentLoc Output;
+ if (TransformTemplateArgument(Input, Output, Uneval))
+ return true; // fails
+ TArgs.push_back(Output.getArgument());
}
- return inherited::TransformTemplateArgument(Input, Output, Uneval);
+ Output = SemaRef.getTrivialTemplateArgumentLoc(
+ TemplateArgument(llvm::ArrayRef(TArgs).copy(SemaRef.Context)),
+ QualType(), SourceLocation{});
+ return false;
+ default:
+ break;
}
+ return inherited::TransformTemplateArgument(Input, Output, Uneval);
+ }
- using TreeTransform::TransformTemplateSpecializationType;
- QualType
- TransformTemplateSpecializationType(TypeLocBuilder &TLB,
- TemplateSpecializationTypeLoc TL) {
- auto *T = TL.getTypePtr();
- if (!getSema().ArgPackSubstIndex || !T->isSugared() ||
- !isPackProducingBuiltinTemplateName(T->getTemplateName()))
- return TreeTransform::TransformTemplateSpecializationType(TLB, TL);
- // Look through sugar to get to the SubstBuiltinTemplatePackType that we
- // need to substitute into.
-
- // `TransformType` code below will handle picking the element from a pack
- // with the index `ArgPackSubstIndex`.
- // FIXME: add ability to represent sugarred type for N-th element of a
- // builtin pack and produce the sugar here.
- QualType R = TransformType(T->desugar());
- TLB.pushTrivial(getSema().getASTContext(), R, TL.getBeginLoc());
- return R;
- }
+ using TreeTransform::TransformTemplateSpecializationType;
+ QualType
+ TransformTemplateSpecializationType(TypeLocBuilder &TLB,
+ TemplateSpecializationTypeLoc TL) {
+ auto *T = TL.getTypePtr();
+ if (!getSema().ArgPackSubstIndex || !T->isSugared() ||
+ !isPackProducingBuiltinTemplateName(T->getTemplateName()))
+ return TreeTransform::TransformTemplateSpecializationType(TLB, TL);
+ // Look through sugar to get to the SubstBuiltinTemplatePackType that we
+ // need to substitute into.
+
+ // `TransformType` code below will handle picking the element from a pack
+ // with the index `ArgPackSubstIndex`.
+ // FIXME: add ability to represent sugarred type for N-th element of a
+ // builtin pack and produce the sugar here.
+ QualType R = TransformType(T->desugar());
+ TLB.pushTrivial(getSema().getASTContext(), R, TL.getBeginLoc());
+ return R;
+ }
- UnsignedOrNone ComputeSizeOfPackExprWithoutSubstitution(
- ArrayRef<TemplateArgument> PackArgs) {
- // Don't do this when rewriting template parameters for CTAD:
- // 1) The heuristic needs the unpacked Subst* nodes to figure out the
- // expanded size, but this never applies since Subst* nodes are not
- // created in rewrite scenarios.
- //
- // 2) The heuristic substitutes into the pattern with pack expansion
- // suppressed, which does not meet the requirements for argument
- // rewriting when template arguments include a non-pack matching against
- // a pack, particularly when rewriting an alias CTAD.
- if (TemplateArgs.isRewrite())
- return std::nullopt;
-
- return inherited::ComputeSizeOfPackExprWithoutSubstitution(PackArgs);
- }
+ UnsignedOrNone ComputeSizeOfPackExprWithoutSubstitution(
+ ArrayRef<TemplateArgument> PackArgs) {
+ // Don't do this when rewriting template parameters for CTAD:
+ // 1) The heuristic needs the unpacked Subst* nodes to figure out the
+ // expanded size, but this never applies since Subst* nodes are not
+ // created in rewrite scenarios.
+ //
+ // 2) The heuristic substitutes into the pattern with pack expansion
+ // suppressed, which does not meet the requirements for argument
+ // rewriting when template arguments include a non-pack matching against
+ // a pack, particularly when rewriting an alias CTAD.
+ if (TemplateArgs.isRewrite())
+ return std::nullopt;
- template<typename Fn>
- QualType TransformFunctionProtoType(TypeLocBuilder &TLB,
- FunctionProtoTypeLoc TL,
- CXXRecordDecl *ThisContext,
- Qualifiers ThisTypeQuals,
- Fn TransformExceptionSpec);
-
- ParmVarDecl *TransformFunctionTypeParam(ParmVarDecl *OldParm,
- int indexAdjustment,
- UnsignedOrNone NumExpansions,
- bool ExpectParameterPack);
-
- using inherited::TransformTemplateTypeParmType;
- /// Transforms a template type parameter type by performing
- /// substitution of the corresponding template type argument.
- QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB,
- TemplateTypeParmTypeLoc TL,
- bool SuppressObjCLifetime);
-
- QualType BuildSubstTemplateTypeParmType(
- TypeLocBuilder &TLB, bool SuppressObjCLifetime, bool Final,
- Decl *AssociatedDecl, unsigned Index, UnsignedOrNone PackIndex,
- TemplateArgument Arg, SourceLocation NameLoc);
-
- /// Transforms an already-substituted template type parameter pack
- /// into either itself (if we aren't substituting into its pack expansion)
- /// or the appropriate substituted argument.
- using inherited::TransformSubstTemplateTypeParmPackType;
- QualType
- TransformSubstTemplateTypeParmPackType(TypeLocBuilder &TLB,
- SubstTemplateTypeParmPackTypeLoc TL,
- bool SuppressObjCLifetime);
- QualType
- TransformSubstBuiltinTemplatePackType(TypeLocBuilder &TLB,
- SubstBuiltinTemplatePackTypeLoc TL);
-
- CXXRecordDecl::LambdaDependencyKind
- ComputeLambdaDependency(LambdaScopeInfo *LSI) {
- if (auto TypeAlias =
- TemplateInstArgsHelpers::getEnclosingTypeAliasTemplateDecl(
- getSema());
- TypeAlias && TemplateInstArgsHelpers::isLambdaEnclosedByTypeAliasDecl(
- LSI->CallOperator, TypeAlias.PrimaryTypeAliasDecl)) {
- unsigned TypeAliasDeclDepth = TypeAlias.Template->getTemplateDepth();
- if (TypeAliasDeclDepth >= TemplateArgs.getNumSubstitutedLevels())
+ return inherited::ComputeSizeOfPackExprWithoutSubstitution(PackArgs);
+ }
+
+ template <typename Fn>
+ QualType TransformFunctionProtoType(TypeLocBuilder &TLB,
+ FunctionProtoTypeLoc TL,
+ CXXRecordDecl *ThisContext,
+ Qualifiers ThisTypeQuals,
+ Fn TransformExceptionSpec);
+
+ ParmVarDecl *TransformFunctionTypeParam(ParmVarDecl *OldParm,
+ int indexAdjustment,
+ UnsignedOrNone NumExpansions,
+ bool ExpectParameterPack);
+
+ using inherited::TransformTemplateTypeParmType;
+ /// Transforms a template type parameter type by performing
+ /// substitution of the corresponding template type argument.
+ QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB,
+ TemplateTypeParmTypeLoc TL,
+ bool SuppressObjCLifetime);
+
+ QualType BuildSubstTemplateTypeParmType(TypeLocBuilder &TLB,
+ bool SuppressObjCLifetime, bool Final,
+ Decl *AssociatedDecl, unsigned Index,
+ UnsignedOrNone PackIndex,
+ TemplateArgument Arg,
+ SourceLocation NameLoc);
+
+ /// Transforms an already-substituted template type parameter pack
+ /// into either itself (if we aren't substituting into its pack expansion)
+ /// or the appropriate substituted argument.
+ using inherited::TransformSubstTemplateTypeParmPackType;
+ QualType
+ TransformSubstTemplateTypeParmPackType(TypeLocBuilder &TLB,
+ SubstTemplateTypeParmPackTypeLoc TL,
+ bool SuppressObjCLifetime);
+ QualType
+ TransformSubstBuiltinTemplatePackType(TypeLocBuilder &TLB,
+ SubstBuiltinTemplatePackTypeLoc TL);
+
+ CXXRecordDecl::LambdaDependencyKind
+ ComputeLambdaDependency(LambdaScopeInfo *LSI) {
+ if (auto TypeAlias =
+ TemplateInstArgsHelpers::getEnclosingTypeAliasTemplateDecl(
+ getSema());
+ TypeAlias && TemplateInstArgsHelpers::isLambdaEnclosedByTypeAliasDecl(
+ LSI->CallOperator, TypeAlias.PrimaryTypeAliasDecl)) {
+ unsigned TypeAliasDeclDepth = TypeAlias.Template->getTemplateDepth();
+ if (TypeAliasDeclDepth >= TemplateArgs.getNumSubstitutedLevels())
+ return CXXRecordDecl::LambdaDependencyKind::LDK_AlwaysDependent;
+ for (const TemplateArgument &TA : TypeAlias.AssociatedTemplateArguments)
+ if (TA.isDependent())
return CXXRecordDecl::LambdaDependencyKind::LDK_AlwaysDependent;
- for (const TemplateArgument &TA : TypeAlias.AssociatedTemplateArguments)
- if (TA.isDependent())
- return CXXRecordDecl::LambdaDependencyKind::LDK_AlwaysDependent;
- }
- return inherited::ComputeLambdaDependency(LSI);
}
+ return inherited::ComputeLambdaDependency(LSI);
+ }
- ExprResult TransformLambdaExpr(LambdaExpr *E) {
- // Do not rebuild lambdas to avoid creating a new type.
- // Lambdas have already been processed inside their eval contexts.
- if (SemaRef.RebuildingImmediateInvocation)
- return E;
- LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true,
- /*InstantiatingLambdaOrBlock=*/true);
- Sema::ConstraintEvalRAII<TemplateInstantiator> RAII(*this);
+ ExprResult TransformLambdaExpr(LambdaExpr *E) {
+ // Do not rebuild lambdas to avoid creating a new type.
+ // Lambdas have already been processed inside their eval contexts.
+ if (SemaRef.RebuildingImmediateInvocation)
+ return E;
+ LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true,
+ /*InstantiatingLambdaOrBlock=*/true);
+ Sema::ConstraintEvalRAII<TemplateInstantiator> RAII(*this);
- return inherited::TransformLambdaExpr(E);
- }
+ return inherited::TransformLambdaExpr(E);
+ }
- ExprResult TransformBlockExpr(BlockExpr *E) {
- LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true,
- /*InstantiatingLambdaOrBlock=*/true);
- return inherited::TransformBlockExpr(E);
- }
+ ExprResult TransformBlockExpr(BlockExpr *E) {
+ LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true,
+ /*InstantiatingLambdaOrBlock=*/true);
+ return inherited::TransformBlockExpr(E);
+ }
- ExprResult RebuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
- LambdaScopeInfo *LSI) {
- CXXMethodDecl *MD = LSI->CallOperator;
- for (ParmVarDecl *PVD : MD->parameters()) {
- assert(PVD && "null in a parameter list");
- if (!PVD->hasDefaultArg())
- continue;
- Expr *UninstExpr = PVD->getUninstantiatedDefaultArg();
- // FIXME: Obtain the source location for the '=' token.
- SourceLocation EqualLoc = UninstExpr->getBeginLoc();
- if (SemaRef.SubstDefaultArgument(EqualLoc, PVD, TemplateArgs)) {
- // If substitution fails, the default argument is set to a
- // RecoveryExpr that wraps the uninstantiated default argument so
- // that downstream diagnostics are omitted.
- ExprResult ErrorResult = SemaRef.CreateRecoveryExpr(
- UninstExpr->getBeginLoc(), UninstExpr->getEndLoc(), {UninstExpr},
- UninstExpr->getType());
- if (ErrorResult.isUsable())
- PVD->setDefaultArg(ErrorResult.get());
- }
+ ExprResult RebuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
+ LambdaScopeInfo *LSI) {
+ CXXMethodDecl *MD = LSI->CallOperator;
+ for (ParmVarDecl *PVD : MD->parameters()) {
+ assert(PVD && "null in a parameter list");
+ if (!PVD->hasDefaultArg())
+ continue;
+ Expr *UninstExpr = PVD->getUninstantiatedDefaultArg();
+ // FIXME: Obtain the source location for the '=' token.
+ SourceLocation EqualLoc = UninstExpr->getBeginLoc();
+ if (SemaRef.SubstDefaultArgument(EqualLoc, PVD, TemplateArgs)) {
+ // If substitution fails, the default argument is set to a
+ // RecoveryExpr that wraps the uninstantiated default argument so
+ // that downstream diagnostics are omitted.
+ ExprResult ErrorResult = SemaRef.CreateRecoveryExpr(
+ UninstExpr->getBeginLoc(), UninstExpr->getEndLoc(), {UninstExpr},
+ UninstExpr->getType());
+ if (ErrorResult.isUsable())
+ PVD->setDefaultArg(ErrorResult.get());
}
- return inherited::RebuildLambdaExpr(StartLoc, EndLoc, LSI);
}
+ return inherited::RebuildLambdaExpr(StartLoc, EndLoc, LSI);
+ }
- StmtResult TransformLambdaBody(LambdaExpr *E, Stmt *Body) {
- // Currently, we instantiate the body when instantiating the lambda
- // expression. However, `EvaluateConstraints` is disabled during the
- // instantiation of the lambda expression, causing the instantiation
- // failure of the return type requirement in the body. If p0588r1 is fully
- // implemented, the body will be lazily instantiated, and this problem
- // will not occur. Here, `EvaluateConstraints` is temporarily set to
- // `true` to temporarily fix this issue.
- // FIXME: This temporary fix can be removed after fully implementing
- // p0588r1.
- llvm::SaveAndRestore _(EvaluateConstraints, true);
- return inherited::TransformLambdaBody(E, Body);
- }
+ StmtResult TransformLambdaBody(LambdaExpr *E, Stmt *Body) {
+ // Currently, we instantiate the body when instantiating the lambda
+ // expression. However, `EvaluateConstraints` is disabled during the
+ // instantiation of the lambda expression, causing the instantiation
+ // failure of the return type requirement in the body. If p0588r1 is fully
+ // implemented, the body will be lazily instantiated, and this problem
+ // will not occur. Here, `EvaluateConstraints` is temporarily set to
+ // `true` to temporarily fix this issue.
+ // FIXME: This temporary fix can be removed after fully implementing
+ // p0588r1.
+ llvm::SaveAndRestore _(EvaluateConstraints, true);
+ return inherited::TransformLambdaBody(E, Body);
+ }
- ExprResult TransformRequiresExpr(RequiresExpr *E) {
- LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true);
- ExprResult TransReq = inherited::TransformRequiresExpr(E);
- if (TransReq.isInvalid())
- return TransReq;
- assert(TransReq.get() != E &&
- "Do not change value of isSatisfied for the existing expression. "
- "Create a new expression instead.");
- if (E->getBody()->isDependentContext()) {
- Sema::SFINAETrap Trap(SemaRef);
- // We recreate the RequiresExpr body, but not by instantiating it.
- // Produce pending diagnostics for dependent access check.
- SemaRef.PerformDependentDiagnostics(E->getBody(), TemplateArgs);
- // FIXME: Store SFINAE diagnostics in RequiresExpr for diagnosis.
- if (Trap.hasErrorOccurred())
- TransReq.getAs<RequiresExpr>()->setSatisfied(false);
- }
+ ExprResult TransformRequiresExpr(RequiresExpr *E) {
+ LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true);
+ ExprResult TransReq = inherited::TransformRequiresExpr(E);
+ if (TransReq.isInvalid())
return TransReq;
+ assert(TransReq.get() != E &&
+ "Do not change value of isSatisfied for the existing expression. "
+ "Create a new expression instead.");
+ if (E->getBody()->isDependentContext()) {
+ Sema::SFINAETrap Trap(SemaRef);
+ // We recreate the RequiresExpr body, but not by instantiating it.
+ // Produce pending diagnostics for dependent access check.
+ SemaRef.PerformDependentDiagnostics(E->getBody(), TemplateArgs);
+ // FIXME: Store SFINAE diagnostics in RequiresExpr for diagnosis.
+ if (Trap.hasErrorOccurred())
+ TransReq.getAs<RequiresExpr>()->setSatisfied(false);
}
+ return TransReq;
+ }
- bool TransformRequiresExprRequirements(
- ArrayRef<concepts::Requirement *> Reqs,
- SmallVectorImpl<concepts::Requirement *> &Transformed) {
- bool SatisfactionDetermined = false;
- for (concepts::Requirement *Req : Reqs) {
- concepts::Requirement *TransReq = nullptr;
- if (!SatisfactionDetermined) {
- if (auto *TypeReq = dyn_cast<concepts::TypeRequirement>(Req))
- TransReq = TransformTypeRequirement(TypeReq);
- else if (auto *ExprReq = dyn_cast<concepts::ExprRequirement>(Req))
- TransReq = TransformExprRequirement(ExprReq);
- else
- TransReq = TransformNestedRequirement(
- cast<concepts::NestedRequirement>(Req));
- if (!TransReq)
- return true;
- if (!TransReq->isDependent() && !TransReq->isSatisfied())
- // [expr.prim.req]p6
- // [...] The substitution and semantic constraint checking
- // proceeds in lexical order and stops when a condition that
- // determines the result of the requires-expression is
- // encountered. [..]
- SatisfactionDetermined = true;
- } else
- TransReq = Req;
- Transformed.push_back(TransReq);
- }
- return false;
+ bool TransformRequiresExprRequirements(
+ ArrayRef<concepts::Requirement *> Reqs,
+ SmallVectorImpl<concepts::Requirement *> &Transformed) {
+ bool SatisfactionDetermined = false;
+ for (concepts::Requirement *Req : Reqs) {
+ concepts::Requirement *TransReq = nullptr;
+ if (!SatisfactionDetermined) {
+ if (auto *TypeReq = dyn_cast<concepts::TypeRequirement>(Req))
+ TransReq = TransformTypeRequirement(TypeReq);
+ else if (auto *ExprReq = dyn_cast<concepts::ExprRequirement>(Req))
+ TransReq = TransformExprRequirement(ExprReq);
+ else
+ TransReq = TransformNestedRequirement(
+ cast<concepts::NestedRequirement>(Req));
+ if (!TransReq)
+ return true;
+ if (!TransReq->isDependent() && !TransReq->isSatisfied())
+ // [expr.prim.req]p6
+ // [...] The substitution and semantic constraint checking
+ // proceeds in lexical order and stops when a condition that
+ // determines the result of the requires-expression is
+ // encountered. [..]
+ SatisfactionDetermined = true;
+ } else
+ TransReq = Req;
+ Transformed.push_back(TransReq);
}
+ return false;
+ }
- TemplateParameterList *TransformTemplateParameterList(
- TemplateParameterList *OrigTPL) {
- if (!OrigTPL || !OrigTPL->size()) return OrigTPL;
-
- DeclContext *Owner = OrigTPL->getParam(0)->getDeclContext();
- TemplateDeclInstantiator DeclInstantiator(getSema(),
- /* DeclContext *Owner */ Owner, TemplateArgs);
- DeclInstantiator.setEvaluateConstraints(EvaluateConstraints);
- return DeclInstantiator.SubstTemplateParams(OrigTPL);
- }
+ TemplateParameterList *
+ TransformTemplateParameterList(TemplateParameterList *OrigTPL) {
+ if (!OrigTPL || !OrigTPL->size())
+ return OrigTPL;
+
+ DeclContext *Owner = OrigTPL->getParam(0)->getDeclContext();
+ TemplateDeclInstantiator DeclInstantiator(getSema(),
+ /* DeclContext *Owner */ Owner,
+ TemplateArgs);
+ DeclInstantiator.setEvaluateConstraints(EvaluateConstraints);
+ return DeclInstantiator.SubstTemplateParams(OrigTPL);
+ }
- concepts::TypeRequirement *
- TransformTypeRequirement(concepts::TypeRequirement *Req);
- concepts::ExprRequirement *
- TransformExprRequirement(concepts::ExprRequirement *Req);
- concepts::NestedRequirement *
- TransformNestedRequirement(concepts::NestedRequirement *Req);
- ExprResult TransformRequiresTypeParams(
- SourceLocation KWLoc, SourceLocation RBraceLoc, const RequiresExpr *RE,
- RequiresExprBodyDecl *Body, ArrayRef<ParmVarDecl *> Params,
- SmallVectorImpl<QualType> &PTypes,
- SmallVectorImpl<ParmVarDecl *> &TransParams,
- Sema::ExtParameterInfoBuilder &PInfos);
- };
-}
+ concepts::TypeRequirement *
+ TransformTypeRequirement(concepts::TypeRequirement *Req);
+ concepts::ExprRequirement *
+ TransformExprRequirement(concepts::ExprRequirement *Req);
+ concepts::NestedRequirement *
+ TransformNestedRequirement(concepts::NestedRequirement *Req);
+ ExprResult TransformRequiresTypeParams(
+ SourceLocation KWLoc, SourceLocation RBraceLoc, const RequiresExpr *RE,
+ RequiresExprBodyDecl *Body, ArrayRef<ParmVarDecl *> Params,
+ SmallVectorImpl<QualType> &PTypes,
+ SmallVectorImpl<ParmVarDecl *> &TransParams,
+ Sema::ExtParameterInfoBuilder &PInfos);
+};
+} // namespace
bool TemplateInstantiator::AlreadyTransformed(QualType T) {
if (T.isNull())
@@ -2767,8 +2765,8 @@ TemplateInstantiator::TransformNestedRequirement(
Req->getConstraintSatisfaction());
return Req;
}
- Sema::InstantiatingTemplate ReqInst(SemaRef,
- Req->getConstraintExpr()->getBeginLoc(), Req,
+ Sema::InstantiatingTemplate ReqInst(
+ SemaRef, Req->getConstraintExpr()->getBeginLoc(), Req,
Sema::InstantiatingTemplate::ConstraintsCheck{},
Req->getConstraintExpr()->getSourceRange());
if (!getEvaluateConstraints()) {
@@ -2790,8 +2788,8 @@ TemplateInstantiator::TransformNestedRequirement(
EnterExpressionEvaluationContext ContextRAII(
SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated);
Sema::SFINAETrap Trap(SemaRef);
- Sema::InstantiatingTemplate ConstrInst(SemaRef,
- Req->getConstraintExpr()->getBeginLoc(), Req, Info,
+ Sema::InstantiatingTemplate ConstrInst(
+ SemaRef, Req->getConstraintExpr()->getBeginLoc(), Req, Info,
Req->getConstraintExpr()->getSourceRange());
if (ConstrInst.isInvalid())
return nullptr;
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 696730148..ac9511467 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -5109,7 +5109,7 @@ bool TreeTransform<Derived>::TransformTemplateArguments(
// all of the template arguments in the argument pack.
typedef TemplateArgumentLocInventIterator<Derived,
TemplateArgument::pack_iterator>
- PackLocIterator;
+ PackLocIterator;
if (TransformTemplateArguments(
PackLocIterator(*this, In.getArgument().pack_begin()),
PackLocIterator(*this, In.getArgument().pack_end()), Outputs,
@@ -5179,7 +5179,6 @@ bool TreeTransform<Derived>::TransformTemplateArguments(
}
return false;
-
}
// FIXME: Find ways to reduce code duplication for pack expansions.
diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp
index 70b898a53..1c3999d69 100644
--- a/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -807,7 +807,7 @@ readConstraintSatisfaction(ASTRecordReader &Record) {
if (!Satisfaction.IsSatisfied) {
unsigned NumDetailRecords = Record.readInt();
for (unsigned i = 0; i != NumDetailRecords; ++i) {
- if (/* IsDiagnostic */Record.readInt()) {
+ if (/* IsDiagnostic */ Record.readInt()) {
SourceLocation DiagLocation = Record.readSourceLocation();
StringRef DiagMessage = C.backupStr(Record.readString());
|
Reverts #141776
CI failures
https://lab.llvm.org/buildbot/#/builders/202/builds/3591
https://lab.llvm.org/buildbot/#/builders/55/builds/18066
https://lab.llvm.org/buildbot/#/builders/85/builds/14103